// 📁 service/impl/BookServiceImpl.java
package com.library.management.service.impl;

import com.library.management.entity.Book;
import com.library.management.entity.BookCategory;
import com.library.management.enums.BookStatus;
import com.library.management.repository.BookRepository;
import com.library.management.service.BookService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;

/**
 * 图书服务实现类
 * 处理图书相关的业务逻辑实现
 */
@Service
@Transactional
@RequiredArgsConstructor
@Slf4j
public class BookServiceImpl implements BookService {

    private final BookRepository bookRepository;

    @Override
    public Book save(Book book) {
        log.info("保存图书: {}", book.getTitle());

        // 设置默认值
        if (book.getAvailableCopies() == null) {
            book.setAvailableCopies(book.getTotalCopies());
        }
        if (book.getStatus() == null) {
            book.setStatus(BookStatus.AVAILABLE);
        }

        return bookRepository.save(book);
    }

    @Override
    public Book update(Long id, Book book) {
        log.info("更新图书: {}", id);

        Book existingBook = bookRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("图书不存在: " + id));

        // 更新允许修改的字段
        existingBook.setTitle(book.getTitle());
        existingBook.setSubtitle(book.getSubtitle());
        existingBook.setAuthor(book.getAuthor());
        existingBook.setTranslator(book.getTranslator());
        existingBook.setPublisher(book.getPublisher());
        existingBook.setPublishDate(book.getPublishDate());
        existingBook.setPublishYear(book.getPublishYear());
        existingBook.setCategory(book.getCategory());
        existingBook.setEdition(book.getEdition());
        existingBook.setPageCount(book.getPageCount());
        existingBook.setLanguage(book.getLanguage());
        existingBook.setPrice(book.getPrice());
        existingBook.setCoverImage(book.getCoverImage());
        existingBook.setSummary(book.getSummary());
        existingBook.setTotalCopies(book.getTotalCopies());
        existingBook.setLocation(book.getLocation());

        // 重新计算可借册数
        updateBookAvailableCopies(id);

        return bookRepository.save(existingBook);
    }

    @Override
    public void delete(Long id) {
        log.info("删除图书: {}", id);

        Book book = bookRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("图书不存在: " + id));

        // 检查图书是否被借出
        if (book.getBorrowedCount() > 0) {
            throw new RuntimeException("图书已被借出，无法删除");
        }

        bookRepository.deleteById(id);
    }
    @Override
    public Book getById(Long id) {
        return bookRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("图书不存在: " + id));
    }
    @Override
    public Optional<Book> findById(Long id) {
        return bookRepository.findById(id);
    }

    @Override
    public List<Book> findAll() {
        return bookRepository.findAll();
    }

    @Override
    public Page<Book> findAll(Pageable pageable) {
        return bookRepository.findAll(pageable);
    }

    @Override
    public boolean exists(Long id) {
        return bookRepository.existsById(id);
    }

    @Override
    public Optional<Book> findByIsbn(String isbn) {
        return bookRepository.findByIsbn(isbn);
    }

    @Override
    public boolean existsByIsbn(String isbn) {
        return bookRepository.existsByIsbn(isbn);
    }

    @Override
    public List<Book> findByTitle(String title) {
        return bookRepository.findByTitle(title);
    }

    @Override
    public List<Book> findByAuthor(String author) {
        return bookRepository.findByAuthor(author);
    }

    @Override
    public List<Book> findByPublisher(String publisher) {
        return bookRepository.findByPublisher(publisher);
    }

    @Override
    public List<Book> findByCategory(BookCategory category) {
        return bookRepository.findByCategory(category);
    }

    @Override
    public List<Book> findByCategoryId(Long categoryId) {
        return bookRepository.findByCategoryId(categoryId);
    }

    @Override
    public List<Book> findByStatus(BookStatus status) {
        return bookRepository.findByStatus(status);
    }

    @Override
    public List<Book> findAvailableBooks() {
        return bookRepository.findByStatusAndAvailableCopiesGreaterThan(BookStatus.AVAILABLE, 0);
    }

    @Override
    public List<Book> searchByTitle(String title) {
        return bookRepository.findByTitleContainingIgnoreCase(title);
    }

    @Override
    public List<Book> searchByAuthor(String author) {
        return bookRepository.findByAuthorContainingIgnoreCase(author);
    }

    @Override
    public List<Book> searchByTitleOrAuthor(String keyword) {
        return bookRepository.findByTitleOrAuthorContaining(keyword);
    }

    @Override
    public List<Book> fullTextSearch(String keyword) {
        return bookRepository.fullTextSearch(keyword);
    }

    @Override
    public List<Book> findByPublishYearRange(Integer startYear, Integer endYear) {
        return bookRepository.findByPublishYearBetween(startYear, endYear);
    }

    @Override
    public List<Book> findByPriceRange(Double minPrice, Double maxPrice) {
        return bookRepository.findByPriceBetween(minPrice, maxPrice);
    }

    @Override
    public Page<Book> findByStatus(BookStatus status, Pageable pageable) {
        return bookRepository.findByStatus(status, pageable);
    }

    @Override
    public Page<Book> findByCategory(BookCategory category, Pageable pageable) {
        return bookRepository.findByCategory(category, pageable);
    }

    @Override
    public List<Book> findPopularBooks(int limit) {
        return bookRepository.findPopularBooks(limit);
    }

    @Override
    public List<Book> findNewBooks(int limit) {
        return bookRepository.findNewBooks(limit);
    }

    @Override
    public boolean borrowBook(Long bookId) {
        log.info("借出图书: {}", bookId);

        Book book = bookRepository.findById(bookId)
                .orElseThrow(() -> new RuntimeException("图书不存在: " + bookId));

        boolean success = book.borrowBook();
        if (success) {
            bookRepository.save(book);
        }

        return success;
    }

    @Override
    public boolean returnBook(Long bookId) {
        log.info("归还图书: {}", bookId);

        Book book = bookRepository.findById(bookId)
                .orElseThrow(() -> new RuntimeException("图书不存在: " + bookId));

        boolean success = book.returnBook();
        if (success) {
            bookRepository.save(book);
        }

        return success;
    }

    @Override
    public void updateBookAvailableCopies(Long bookId) {
        // 这个功能由数据库触发器处理，这里可以留空或添加其他逻辑
        log.debug("更新图书可借册数: {}", bookId);
    }

    @Override
    public long countByStatus(BookStatus status) {
        return bookRepository.countByStatus(status);
    }

    @Override
    public List<Object[]> countBooksByCategory() {
        return bookRepository.countBooksByCategory();
    }

    @Override
    public boolean isBookAvailableForBorrow(Long bookId) {
        Book book = bookRepository.findById(bookId)
                .orElseThrow(() -> new RuntimeException("图书不存在: " + bookId));

        return book.isAvailableForBorrow();
    }

    @Override
    public long getBorrowCount(Long bookId) {
        Book book = bookRepository.findById(bookId)
                .orElseThrow(() -> new RuntimeException("图书不存在: " + bookId));

        return book.getBorrowCount();
    }

    @Override
    public int getBorrowedCount(Long bookId) {
        Book book = bookRepository.findById(bookId)
                .orElseThrow(() -> new RuntimeException("图书不存在: " + bookId));

        return book.getBorrowedCount();
    }
}